package com.et114.core.utility;

import java.lang.reflect.Field;
//import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.util.Assert;
//import org.apache.commons.collections.CollectionUtils;
//import org.springframework.util.ReflectionUtils;

/**
 * @author guanhw 扩展Apache Commons BeanUtils, 提供一些反射方面缺失功能的封装.
 */
public class BeanUtils extends org.apache.commons.beanutils.BeanUtils {
	protected static final Log	logger	= LogFactory.getLog( BeanUtils.class );

	private BeanUtils ( ) {
	}

	/**
	 * 循环向上转型,获取对象的DeclaredField.
	 * 
	 * @throws NoSuchFieldException如果没有该Field时抛出.
	 */
	public static Field getDeclaredField ( Object object , String propertyName )
			throws NoSuchFieldException {
		Assert.notNull( object );
		Assert.hasText( propertyName );
		return getDeclaredField( object.getClass(), propertyName );
	}

	/**
	 * 循环向上转型,获取对象的DeclaredField.
	 * 
	 * @throws NoSuchFieldException如果没有该Field时抛出.
	 */
	public static Field getDeclaredField ( Class clazz , String propertyName )
			throws NoSuchFieldException {
		Assert.notNull( clazz );
		Assert.hasText( propertyName );
		for ( Class superClass = clazz; superClass != Object.class; superClass = superClass
				.getSuperclass() ) {
			try {
				return superClass.getDeclaredField( propertyName );
			} catch ( NoSuchFieldException e ) {
				// Field不在当前类定义,继续向上转型
			}
		}
		throw new NoSuchFieldException( "No such field: " + clazz.getName()
				+ '.' + propertyName );
	}

	/**
	 * 暴力获取对象变量值,忽略private,protected修饰符的限制.
	 * 
	 * @throws NoSuchFieldException
	 *             如果没有该Field时抛出.
	 */
	public static Object forceGetProperty ( Object object , String propertyName )
			throws NoSuchFieldException {
		Assert.notNull( object );
		Assert.hasText( propertyName );

		Field field = getDeclaredField( object, propertyName );

		boolean accessible = field.isAccessible();
		field.setAccessible( true );

		Object result = null;
		try {
			result = field.get( object );
		} catch ( IllegalAccessException e ) {
			logger.info( "error wont' happen" );
		}
		field.setAccessible( accessible );
		return result;
	}

	/**
	 * 暴力设置对象变量值,忽略private,protected修饰符的限制.
	 * 
	 * @throws NoSuchFieldException
	 *             如果没有该Field时抛出.
	 */
	public static void forceSetProperty ( Object object , String propertyName ,
			Object newValue ) throws NoSuchFieldException {
		Assert.notNull( object );
		Assert.hasText( propertyName );

		Field field = getDeclaredField( object, propertyName );
		boolean accessible = field.isAccessible();
		field.setAccessible( true );
		try {
			field.set( object, newValue );
		} catch ( IllegalAccessException e ) {
			logger.info( "Error won't happen" );
		}
		field.setAccessible( accessible );
	}

	/**
	 * 暴力调用对象函数,忽略private,protected修饰符的限制.
	 * 
	 * @throws NoSuchMethodException
	 *             如果没有该Method时抛出.
	 */

	/*
	 * public static Object invokePrivateMethod(Object object, String
	 * methodName, Object... params) throws NoSuchMethodException {
	 * Assert.notNull(object); Assert.hasText(methodName); Class[] types = new
	 * Class[params.length]; for (int i = 0; i < params.length; i++) { types[i] =
	 * params[i].getClass(); }
	 * 
	 * Class clazz = object.getClass(); Method method = null; for (Class
	 * superClass = clazz; superClass != Object.class; superClass =
	 * superClass.getSuperclass()) { try { method =
	 * superClass.getDeclaredMethod(methodName, types); break; } catch
	 * (NoSuchMethodException e) { // 方法不在当前类定义,继续向上转型 } }
	 * 
	 * if (method == null) throw new NoSuchMethodException("No Such Method:" +
	 * clazz.getSimpleName() + methodName);
	 * 
	 * boolean accessible = method.isAccessible(); method.setAccessible(true);
	 * Object result = null; try { result = method.invoke(object, params); }
	 * catch (Exception e) { ReflectionUtils.handleReflectionException(e); }
	 * method.setAccessible(accessible); return result; }
	 */

	/**
	 * 按Filed的类型取得Field列表.
	 */
	public static List getFieldsByType ( Object object , Class type ) {
		List list = new ArrayList();
		Field [ ] fields = object.getClass().getDeclaredFields();
		for ( int i = 0; i < fields.length; i++ ) {
			Field field = fields [ i ];
			if ( field.getType().isAssignableFrom( type ) ) {
				list.add( field );
			}
		}

		return list;
	}

	/**
	 * 按FiledName获得Field的类型.
	 */
	public static Class getPropertyType ( Class type , String name )
			throws NoSuchFieldException {
		return getDeclaredField( type, name ).getType();
	}

	/**
	 * 获得field的getter函数名称.
	 */
	public static String getGetterName ( Class type , String fieldName ) {
		Assert.notNull( type, "Type required" );
		Assert.hasText( fieldName, "FieldName required" );

		if ( type.getName().equals( "boolean" ) ) {
			return "is" + StringUtils.capitalize( fieldName );
		} else {
			return "get" + StringUtils.capitalize( fieldName );
		}
	}

	/**
	 * 获得field的getter函数,如果找不到该方法,返回null.
	 */
	/*
	 * public static Method getGetterMethod(Class type, String fieldName) { try {
	 * return type.getMethod(getGetterName(type, fieldName)); } catch
	 * (NoSuchMethodException e) { logger.error(e.getMessage(), e); } return
	 * null; }
	 */
}
